﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Modbus.Device;
using Modbus.Message;

namespace modbusEx
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Init();
            serialPort = new SerialPort();
            master = ModbusSerialMaster.CreateRtu(serialPort);

        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                ReciveData();
            }

        }

        public void Init()
        {
            List<string> lst = new List<string>();
            lst.AddRange(SerialPort.GetPortNames().ToList());
            foreach (string item in lst)
            {
                this.SerialPortList.Items.Add(item);
            }
            this.SerialPortList.SelectedIndex = 0;
            this.BaudList.Items.Add(4800);
            this.BaudList.Items.Add(9600);
            this.BaudList.Items.Add(19200);
            this.BaudList.Items.Add(115200);
            this.BaudList.SelectedIndex = 1;
            this.ParityList.Items.Add("NONE");
            this.ParityList.Items.Add("EVEN");
            this.ParityList.Items.Add("ODD");
            this.ParityList.SelectedIndex = 0;
            this.DataBits.Items.Add(6);
            this.DataBits.Items.Add(7);
            this.DataBits.Items.Add(8);
            this.DataBits.SelectedIndex = 2;
            this.StopBits.Items.Add(1);
            this.StopBits.Items.Add(2);
            this.StopBits.SelectedIndex = 0;
            this.Options.Items.Add("01 Coil Status (0x)");
            this.Options.Items.Add("02 Input Status (1x)");
            this.Options.Items.Add("03 Holding Register (4x)");
            this.Options.Items.Add("04 Input Register (3x)");
            this.Options.SelectedIndex = 1;
            this.SlaveID.Value = 1;
            this.Count.Value = 8;
        }
        public SerialPort serialPort { get; set; }
        public ModbusMaster master;
        public string option = string.Empty;
        private void button1_Click(object sender, EventArgs e)
        {
            if (this.btnOpen.Text == "打开串口")
            {
                serialPort.Open();
                this.btnOpen.Text = "关闭串口";
                this.Status.BackColor = Color.Green;
                option = Options.SelectedItem.ToString();
                Thread thread = new Thread(new ThreadStart(new Action(() =>
                {
                    while (true)
                    {
                        Thread.Sleep(1000);
                        ReciveData();
                    }
                })));
                thread.IsBackground = true;
                thread.Start();
            }
            else
            {
                serialPort.Close(); this.btnOpen.Text = "打开串口"; this.Status.BackColor = Color.Red;
            }

        }
        //发送数据
        private void button2_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                if (this.Send.Text.Length > 0)
                {
                    if (this.Options.SelectedItem.ToString() == "01 Coil Status (0x)")
                    {
                        if (this.Send.Text.Trim() == "true" || this.Send.Text.Trim() == "false")
                        {

                            master.WriteSingleCoil((byte)this.SlaveID.Value, (byte)this.StartAddress.Value, bool.Parse(this.Send.Text.Trim()));
                            MessageBox.Show("发送成功！");
                            WriteSingleCoilRequestResponse writeSingleCoilRequestResponse = new WriteSingleCoilRequestResponse((byte)this.SlaveID.Value, (byte)this.StartAddress.Value, bool.Parse(this.Send.Text.Trim()));
                            this.Sendmessage.Text = writeSingleCoilRequestResponse.ToString();

                        }
                        else
                        {
                            MessageBox.Show("请输入ture或者false");
                        }

                    }
                    else if (this.Options.SelectedItem.ToString() == "02 Input Status (1x)")
                    {
                        MessageBox.Show("该模式只能读取！");
                    }
                    else if (this.Options.SelectedItem.ToString() == "03 Holding Register (4x)")
                    {
                        try
                        {
                            ushort data = ushort.Parse(this.Send.Text.Trim());
                            master.WriteSingleRegister((byte)this.SlaveID.Value, (ushort)this.StartAddress.Value, data);
                            MessageBox.Show("发送成功！");
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message,"错误！");

                        }
                       
                    }
                    else if (this.Options.SelectedItem.ToString() == "04 Input Register (3x)")
                    {
                        MessageBox.Show("该模式只能读取！");
                    }
                }
                else MessageBox.Show("发送数据不能为空！");

            }
            else { MessageBox.Show("串口未打开！"); };
        }
        //接收数据
        public void ReciveData()
        {
            if (option == "01 Coil Status (0x)" || option == "02 Input Status (1x)")
            {
                bool[] data = new bool[(int)this.Count.Value];
                if (this.Count.Value > 0)
                {
                    data = master.ReadCoils((byte)this.SlaveID.Value, (ushort)this.StartAddress.Value, (ushort)this.Count.Value);
                    this.Recive.Text = string.Join(" ", data);
                }

                ReadCoilsInputsRequest readCoilsReq = new ReadCoilsInputsRequest(0x01, (byte)this.SlaveID.Value, (ushort)this.StartAddress.Value, (ushort)this.Count.Value);
                var readCoilsRes = master.ExecuteCustomMessage<ReadCoilsInputsResponse>(readCoilsReq);
                this.Recivemessage.Text = readCoilsReq.ToString();
            }
            else if (option == "03 Holding Register (4x)" || option == "04 Input Register (3x)")
            {

                if (this.Count.Value > 0)
                {
                    var data = master.ReadHoldingRegisters((byte)this.SlaveID.Value, (ushort)this.StartAddress.Value, (ushort)this.Count.Value);
                    Recive.Invoke(new Action(() =>
                    {
                        this.Recive.Text = string.Join(" ", data);
                    }));
                }
            }

        }
        //设置串口对象
        public void CreateSingle()
        {
            serialPort.PortName = this.SerialPortList.SelectedItem.ToString();
            serialPort.BaudRate = (int)this.BaudList.SelectedItem;
            switch (this.ParityList.SelectedItem.ToString())
            {
                case "NONE":
                    serialPort.Parity = Parity.None;
                    break;
                case "EVEN":
                    serialPort.Parity = Parity.Even;
                    break;
                case "ODD":
                    serialPort.Parity = Parity.Odd;
                    break;

            }

            serialPort.DataBits = (int)this.DataBits.SelectedItem;
            serialPort.StopBits = (StopBits)this.StopBits.SelectedItem;
        }
        //清空数据
        private void button1_Click_1(object sender, EventArgs e)
        {
            this.Send.Text = string.Empty;

        }

        private void button3_Click(object sender, EventArgs e)
        {
            this.Recive.Text = string.Empty;
        }

        private void Options_SelectedIndexChanged(object sender, EventArgs e)
        {
            option = Options.SelectedItem.ToString();
        }
    }
}
